package com.kinghood.productcenter.service.product.impl;

import com.alibaba.cloud.commons.io.Charsets;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kinghood.infrastructure.api.authority.SysLogModuleEnum;
import com.kinghood.infrastructure.api.authority.UserRemoteVo;
import com.kinghood.infrastructure.model.KingHoodException;
import com.kinghood.infrastructure.model.KingHoodResponseVO;
import com.kinghood.infrastructure.model.constant.CommonConstants;
import com.kinghood.infrastructure.model.dto.IdValueDTO;
import com.kinghood.infrastructure.util.UserUtil;
import com.kinghood.infrastructure.util.base.IdGenUtil;
import com.kinghood.productcenter.common.api.authority.UserRemote;
import com.kinghood.productcenter.common.model.dao.product.DownloadCenterDO;
import com.kinghood.productcenter.common.model.dto.base.ListDownloadQueryDTO;
import com.kinghood.productcenter.common.model.vo.product.DownloadVO;
import com.kinghood.productcenter.common.utils.UserNameUtil;
import com.kinghood.productcenter.dao.product.DownloadCenterMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kinghood.productcenter.service.product.IDownloadCenterService;
import com.kinghood.sharding.model.KingHoodPageUtil;
import com.kinghood.sharding.model.KingPageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 下载中心 服务实现类
 * </p>
 *
 * @author KingHood
 * @since 2023-12-20
 */
@Service
@Slf4j
public class DownloadCenterServiceImpl extends ServiceImpl<DownloadCenterMapper, DownloadCenterDO> implements IDownloadCenterService {
    @Resource
    private UserRemote userRemote;
    @Value("${base.uploadPath}")
    private String uploadPath;

    /**
     * 添加上传文件
     *
     * @param module   单元
     * @param type     类型
     * @param fileName 文件名
     * @param size     大小
     * @param url      url
     * @return
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public Long addUploadFile(Integer module, Integer type, String fileName, String size, String url) {
        DownloadCenterDO one = new DownloadCenterDO();
        one.setId(IdGenUtil.getId());
        one.setModule(module);
        one.setType(type);
        one.setFileName(fileName);
        one.setFileSize(size);
        one.setDownNum(0);
        one.setUrl(url);
        one.setCreateTime(LocalDateTime.now());
        one.setUpdateTime(LocalDateTime.now());
        one.setCreateUserId(UserUtil.getUserId());
        one.setUpdateUserId(UserUtil.getUserId());
        this.save(one);
        return one.getId();
    }

    /**
     * 列表文件
     *
     * @param param 参数
     * @return @return {@link Object }
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public Object listFile(ListDownloadQueryDTO param) {
        KingHoodResponseVO<List> remoteInfo = userRemote.userMenuList(UserUtil.getUserId());
        if (remoteInfo.getSuccess()) {
            List<String> userDTO = remoteInfo.getData();
            if (!CollectionUtils.isEmpty(userDTO)) {
                param.setModuleAuth(new ArrayList<>());
                if (userDTO.contains("/product/style")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_PRODUCT.getType());
                }
                if (userDTO.contains("/product/classify/cargo")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_GOODS.getType());
                }
                if (userDTO.contains("/product/classify/category")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_CATEGORY.getType());
                }
                if (userDTO.contains("/product/basic/attribute")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_ATTRIBUTE.getType());
                }
                if (userDTO.contains("/product/basic/label")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_LABEL.getType());
                }
                if (userDTO.contains("/product/business/brand")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_BRAND.getType());
                }
                if (userDTO.contains("/product/business/supplier")) {
                    param.getModuleAuth().add(SysLogModuleEnum.PRODUCT_SUPPLIER.getType());
                }
            }
        }

        Page<DownloadVO> result = this.baseMapper.listFile(KingHoodPageUtil.getPage(param, param), param);

        Set<Long> userIdList = new HashSet<>();
        for (DownloadVO record : result.getRecords()) {
            userIdList.add(record.getCreateUserId());
            record.setModuleTxt(SysLogModuleEnum.getNameByType(record.getModule()));
        }
        userIdList.remove(null);
        if (!CollectionUtils.isEmpty(userIdList)) {
            Map<Long, UserRemoteVo> userMap = userRemote.getUserByIds(new ArrayList<Long>(userIdList));
            for (DownloadVO record : result.getRecords()) {
                record.setCreateUserName(UserNameUtil.getName(record.getCreateUserId(), userMap));
            }
        }
        return KingPageResult.getResult(result);
    }

    /**
     * 模块列表
     *
     * @return @return {@link List }<{@link IdValueDTO }>
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public List<IdValueDTO> listModule() {
        List<IdValueDTO> result = new ArrayList<>();

        KingHoodResponseVO<List> remoteInfo = userRemote.userMenuList(UserUtil.getUserId());
        if (remoteInfo.getSuccess()) {
            List<String> userDTO = remoteInfo.getData();
            if (!CollectionUtils.isEmpty(userDTO)) {
                for (String path : userDTO) {
                    IdValueDTO idValueDTO = new IdValueDTO();
                    SysLogModuleEnum moduleEnum = null;
                    if (path.contains("/product/style")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_PRODUCT;
                    } else if (path.contains("/product/classify/cargo")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_GOODS;
                    } else if (path.contains("/product/classify/category")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_CATEGORY;
                    } else if (path.contains("/product/basic/attribute")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_ATTRIBUTE;
                    } else if (path.contains("/product/basic/label")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_LABEL;
                    } else if (path.contains("/product/business/brand")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_BRAND;
                    } else if (path.contains("/product/business/supplier")) {
                        moduleEnum = SysLogModuleEnum.PRODUCT_SUPPLIER;
                    }
                    idValueDTO.setId(moduleEnum.getType());
                    idValueDTO.setValue(moduleEnum.getName());
                    result.add(idValueDTO);
                }
            }
        }
        return result.stream().sorted(Comparator.comparing(IdValueDTO::getId)).collect(Collectors.toList());
    }

    /**
     * 删除文件
     *
     * @param id 身份证件
     * @return
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public void delFile(Long id) {
        this.lambdaUpdate().set(DownloadCenterDO::getIsDelete, CommonConstants.IS_DELETE_Y)
                .set(DownloadCenterDO::getUpdateTime, LocalDateTime.now())
                .set(DownloadCenterDO::getUpdateUserId, UserUtil.getUserId())
                .eq(DownloadCenterDO::getId, id)
                .update();
    }

    /**
     * 下载文件
     *
     * @param id       身份证件
     * @param response 回答
     * @param request  要求
     * @return
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public void downloadFile(Long id, HttpServletResponse response, HttpServletRequest request) {
        DownloadCenterDO fileDo = this.lambdaQuery().eq(DownloadCenterDO::getIsDelete, CommonConstants.IS_DELETE_N)
                .eq(DownloadCenterDO::getId, id)
                .one();
        if (Objects.isNull(fileDo)) {
            throw new KingHoodException(-1, "文件不存在");
        }
        fileDo.setDownNum(fileDo.getDownNum() + 1);
        this.updateById(fileDo);
        // 本地文件地址，文件名称，我是在本机运行，如果是服务器的话，地址可能是 ../fileServer/file/deploy2.sh
        String filePath = fileDo.getUrl();
        String fileName = fileDo.getFileName();

        // 获取浏览器的信息
        String agent = request.getHeader("USER-AGENT");
        /*if (agent != null && agent.toLowerCase().indexOf(FIRE_FOX) > 0) {
            //火狐浏览器自己会对URL进行一次URL转码所以区别处理
            response.setHeader("Content-Disposition",
                    "attachment; filename=" + new String(fileName.getBytes("GB2312"), "ISO-8859-1"));
        } else if (agent.toLowerCase().indexOf(SAFARI) > 0) {
            //苹果浏览器需要用ISO 而且文件名得用UTF-8
            response.setHeader("Content-Disposition",
                    "attachment; filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        } else {
        }*/

        try {
            //其他的浏览器
            response.setHeader("Content-disposition",
                    "attachment;filename*=utf-8''" + java.net.URLEncoder.encode(fileName, "UTF-8"));
            File file = new File(filePath);
            FileInputStream fileInputStream = new FileInputStream(file);

            byte[] fileByte = new byte[(int) file.length()];
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fileInputStream.read(bytes, 0, bytes.length)) != -1) {
                byteArrayOutputStream.write(bytes, 0, len);
            }
            byteArrayOutputStream.close();
            fileByte = byteArrayOutputStream.toByteArray();

            OutputStream outputStream = null;
            outputStream = response.getOutputStream();
            outputStream.write(fileByte);
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     *
     * @param file 文件
     * @return
     * @author jp
     * @date 2024/01/12 14:59
     */
    @Override
    public void uploadFile(MultipartFile file) {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        log.info("上传文件原始的名字: " + fileName);
        // 使用uuid生成新文件名
        String newFileName = fileName.substring(0,fileName.lastIndexOf("."))
                +UUID.randomUUID().toString().replaceAll("-", "")
                + fileName.substring(fileName.lastIndexOf("."), fileName.length());
        log.info("保存的文件的新名字: " + newFileName);

        // 获取年月日的日期格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());

        // 生成以日期分割的文件路径
        File readPath = new File(uploadPath + File.separator + format);
        log.info("存放的文件夹: " + readPath);
        String absolutePath = readPath.getAbsolutePath();
        log.info("存放文件的绝对路径: " + absolutePath);
        // 判断文件夹是否存在
        if (!readPath.isDirectory()) {
            // 创建文件夹
            readPath.mkdirs();
        }

        // 文件真实的保存路径
        File reafFile = new File(readPath.getAbsolutePath() + File.separator + newFileName);

        try {
            if (!reafFile.exists()) {
                reafFile.createNewFile();
            }
            file.transferTo(reafFile);
        } catch (Exception e) {
            log.error("文件上传异常:",e);
        }
    }

    /**
     * 增加下载次数
     *
     * @param id 身份证件
     * @return
     * @author jp
     * @date 2024/01/29 14:45
     */
    @Override
    public void addFrequency(Long id) {
        this.baseMapper.addFrequency(id);
    }
}
